#include "stdafx.h"
#include "windows.h"
#include "LFThreadPool.h"

const DWORD KNoLeader = 0;

namespace Network {
	ThreadMutex iSynchronizer;
	ThreadMutex iFollowerCondition; //followers will wait on this condition
	
	ThreadMutex iReactSync;

	LFThreadPool::LFThreadPool( SelectReactor* reactor, unsigned int threadCount )
	{
		iReactor = reactor;
		iLeaderThread = KNoLeader; 
		iIsRunning = false;
	}

	LFThreadPool::~LFThreadPool(void)
	{
		iIsRunning = false;
	
		//WakeAllConditionVariable(&iLFCondSynchronizer); 
		//delete &iLFCondSynchronizer;

		// cancel created threads
		//for( unsigned int i = 0; i < iNumOfThreads; i++ ) {
		//	CloseHandle( iThreadidps[i] );
		//} 
	}

	DWORD LFThreadPool::Join( DWORD timeout_ms )
	{
		Guard guard( iSynchronizer );

		DWORD thisThread = GetCurrentThreadId();
		
		while( iIsRunning ) 
		{
			DWORD dwResultEvent = NULL; 
			//skip this if we are the leader
			while( iLeaderThread != KNoLeader && iLeaderThread != thisThread) {
				//printf("wait start - 0x%x\n", thisThread);
				iSynchronizer.Release();
				iFollowerCondition.Acquire(10); //follower role
				iSynchronizer.Acquire();
				//printf("wait end - 0x%x\n", thisThread);
			}
			
			iLeaderThread = GetCurrentThreadId(); //assume leader position
			printf("Current leader is the thread with ID = 0x%x\n", iLeaderThread);

			guard.Release(); //allow other threads to join the pool

			SelectReactor::instance()->handle_events();
			
			guard.Acquire();
		}

		return 0;
	}

	void LFThreadPool::PromoteNewLeader( )
	{
		Guard guard ( iSynchronizer );

		if( iLeaderThread != GetCurrentThreadId() ) {
			printf("Non-leader cannot promote new leader !\n");
			return;
		}

		printf("Promoting new leader ... \n");
		
		iLeaderThread = KNoLeader;
		iFollowerCondition.Release();
	}

	void LFThreadPool::Start()
	{
		iIsRunning = true;
	}

	void LFThreadPool::Stop()
	{
		iIsRunning = false;
	}

	void LFThreadPool::DeactivateHandle(HANDLE handler, EventType et){
		SelectReactor::instance()->suspend_handle(handler, et);
	}

	void LFThreadPool::ActivateHandle(HANDLE handler, EventType et){
		SelectReactor::instance()->resume_handle(handler, et);
	}
}